package Hunters;

import AGENTS.*;
import Settings.BotKiller;
import Settings.Parameters;
import cz.cuni.amis.pogamut.base.agent.navigation.IPathExecutorState;
import cz.cuni.amis.pogamut.base.agent.params.IRemoteAgentParameters;
import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004AStarPathPlanner;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004GetBackToNavGraph;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004Navigation;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004RunStraight;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.floydwarshall.FloydWarshallMap;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.stuckdetector.UT2004DistanceStuckDetector;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.stuckdetector.UT2004PositionStuckDetector;
import cz.cuni.amis.pogamut.ut2004.agent.navigation.stuckdetector.UT2004TimeStuckDetector;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotModuleController;
import cz.cuni.amis.pogamut.ut2004.communication.messages.UT2004ItemType;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Initialize;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.*;
import cz.cuni.amis.pogamut.ut2004.utils.UT2004BotRunner;
import cz.cuni.amis.utils.exception.PogamutException;
import cz.cuni.amis.utils.flag.FlagListener;

import java.util.logging.Level;
import java.util.logging.Logger;


@SuppressWarnings("rawtypes")
public class MirrorBot4 extends UT2004BotModuleController {

    private MyNavigator myNav = null;
    private AGENTS_Mirror agents = null;
    private RayData rayData = null;
    private double lastTime = 0.0;
    private boolean initTime = false;

    //////////////////////////////////////////////
    public void endEval() {
        BotKiller.killBot(bot);
    }


    ////////////////////////////////////////////////
    public AGENTS_Mirror getAgents() {
        return agents;
    }

    ////////////////////////////////////////////////////
    @Override
    public void logic() throws PogamutException {
        try {
            if (!initTime) {
                lastTime = System.currentTimeMillis();
                initTime = true;
            }
            double dt = (System.currentTimeMillis() - lastTime) / 1000.0;
            lastTime = System.currentTimeMillis();

            if (Parameters.parameters == null || Parameters.parameters.booleanParameter("utBotLogOutput")) {
                System.out.println(info.getName() + ":");
            }
            agents.execute(dt);
        } catch (Exception e) {
            System.out.println("BUG found");
            e.printStackTrace();
        }
    }

    ////////////////////////////////////////////////
    @Override
    public void botKilled(BotKilled event) {
        if (agents != null) {
            agents.deathClean();
        }
    }

    ///////////////////////////////////////////////
    @Override
    public void botFirstSpawn(GameInfo gameInfo, ConfigChange config, InitedMessage init, Self self) {
    }

    /////////////////////////////////////////////
    @Override
    public void beforeFirstLogic() {
    }

    /////////////////////////////////////////////////////
    @Override
    public void botInitialized(GameInfo gameInfo, ConfigChange currentConfig, InitedMessage init) {
        rayData = new RayData(this);
        if (myNav != null) {
            myNav.getRunner().setRayData(rayData);
        }
        agents = new AGENTS_Mirror(this, rayData);

        getNavigation().getPathExecutor().getState().addStrongListener(new FlagListener<IPathExecutorState>() {
            @Override
            public void flagChanged(IPathExecutorState changedValue) {
                agents.pathExecutorStateChange(changedValue.getState());
            }
        });
    }

    ////////////////////////////////////////////////
    @Override
    public void prepareBot(UT2004Bot bot) {
        // DEFINE WEAPON PREFERENCES
        weaponPrefs.addGeneralPref(UT2004ItemType.MINIGUN, false);
        weaponPrefs.addGeneralPref(UT2004ItemType.MINIGUN, true);
        //weaponPrefs.addGeneralPref(ItemType.LINK_GUN, false);
        weaponPrefs.addGeneralPref(UT2004ItemType.LIGHTNING_GUN, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.SHOCK_RIFLE, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.ROCKET_LAUNCHER, true);
        //weaponPrefs.addGeneralPref(ItemType.LINK_GUN, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.ASSAULT_RIFLE, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.FLAK_CANNON, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.FLAK_CANNON, false);
        weaponPrefs.addGeneralPref(UT2004ItemType.BIO_RIFLE, true);
        weaponPrefs.addGeneralPref(UT2004ItemType.SHIELD_GUN, true);
    }

    ///////////////////////////////////////////////

    @Override
    protected void initializePathFinding(UT2004Bot bot) {
        //System.out.println("SUCCESS HACK");
        Logger myLog = Logger.getAnonymousLogger();
        if (myLog == null) {
            myLog = log;
        } else {
            myLog.setLevel(Level.OFF);
        }
        ut2004PathPlanner = new UT2004AStarPathPlanner(bot);
        fwMap = new FloydWarshallMap(bot);
        myNav = new MyNavigator(bot, myLog);
        MyPathExecutor<ILocated> pathExecutor = new MyPathExecutor<ILocated>(bot, info, move, myNav, myLog);
        pathExecutor.addStuckDetector(new UT2004TimeStuckDetector(bot, 3000, 100000));
        pathExecutor.addStuckDetector(new UT2004PositionStuckDetector(bot));
        pathExecutor.addStuckDetector(new UT2004DistanceStuckDetector(bot));
        UT2004GetBackToNavGraph getBackToNavGraph = new UT2004GetBackToNavGraph(bot, info, move);
        UT2004RunStraight runStraight = new UT2004RunStraight(bot, info, move);
        navigation = new UT2004Navigation(bot, pathExecutor, fwMap, getBackToNavGraph, runStraight);
    }

    //////////////////////////////////////////////////
    @Override
    public Initialize getInitializeCommand() {
        Initialize init = null;

        try {
            init = new Initialize();
        } catch (Exception e) {
        }

        if (init != null) {
            init.setName("MirrorBot");
            init.setAutoPickupOff(false);
            init.setDesiredSkill(2 + (int) (Math.random() * 5));
            init.setSkin("HumanFemaleA.EgyptFemaleA");
        }

        return init;
    }

    /////////////////////////////////////////////////
    private static int agent_num = 2;

    public static void main(String args[]) throws PogamutException {
        Class[] botClasses = new Class[]{MirrorBot4.class};
        IRemoteAgentParameters[] params = new IRemoteAgentParameters[]{new MirrorBotParameters()};
        //MultiBotLauncher.launchMultipleBots(botClasses, params, "localhost", 3000);//launchMultipleBots(botClasses, params, "localhost", 3000);
        new UT2004BotRunner(MirrorBot4.class, "MirrorBot4").setMain(true).setLogLevel(Level.INFO).startAgents(agent_num);
    }
}
